#include <cassert>
#include <ctime>
#include <iostream>

#include "PredatorStates.h"
#include "Entity/EntityManager.h"
#include "Entity/Game/Prey.h"
#include "Message/MessageDispatcher.h"


//! PredatorStateSeek
PredatorStateSeek* PredatorStateSeek::GetInstance()
{
	static PredatorStateSeek instance;
	return &instance;
}

void PredatorStateSeek::Enter(Predator* p)
{
	std::cout << p->GetEnityName() << "<PredatorStateSeek::Enter>: Began Seeking\n";
}

void PredatorStateSeek::Execute(Predator* p)
{
	srand((unsigned int)time(0));
	int r = rand() % 5 + 1;

	if (r == 1)
	{
		EntityManager& entityManager = EntityManager::GetInstance();
		BaseEntity* entity = entityManager.GetRandomEntityOfType<Prey>();
		
		assert(entity && "<PredatorStateSeek::Execute>: Entity == NULL\n");

		if (entity)
		{
			MessageDispatcher& messageDispatcher = MessageDispatcher::GetInstance();
			
			p->GetStateMachine()->ChangeCurrentState(PredatorStateChase::GetInstance());
			p->SetCurrentPreyID(entity->ID());
			
			messageDispatcher.DispatchMessage(0, p->ID(), entity->ID(), AITypes::DETECTED_BY_PREDATOR, NULL);			
		}
	}
}

void PredatorStateSeek::Exit(Predator* p)
{
	std::cout << p->GetEnityName() << "<PredatorStateSeek::Exit>: Message Received: Finished Seeking\n";
}

bool PredatorStateSeek::OnMessage(Predator* p, const Message& m)
{
	std::cout << p->GetEnityName() << "<PredatorStateSeek::OnMessage>: Message Received\n";

	return true;
}


//! PredatorStateChase
PredatorStateChase* PredatorStateChase::GetInstance()
{
	static PredatorStateChase instance;
	return &instance;
}

void PredatorStateChase::Enter(Predator* p)
{
	std::cout << p->GetEnityName() << "<PredatorStateChase::Enter>: Began Chasing\n";
}

void PredatorStateChase::Execute(Predator* p)
{
	srand((unsigned int)time(0));
	int r = rand() % 100 + 1;

	if (r == 1)
	{
		EntityManager& entityManager = EntityManager::GetInstance();
	}


}

void PredatorStateChase::Exit(Predator* p)
{
	std::cout << p->GetEnityName() << "<PredatorStateChase::Exit>: Message Received: Finished Chasing\n";
}

bool PredatorStateChase::OnMessage(Predator* p, const Message& m)
{
	std::cout << p->GetEnityName() << "<PredatorStateChase::OnMessage>: Message Received\n";

	if (m.m_message == AITypes::EVADED_PREDATOR)
	{
		p->GetStateMachine()->ChangeCurrentState(PredatorStateSeek::GetInstance());

		//todo: should make this a typedef, enum or something
		p->SetCurrentPreyID(-1);
	}
	
	return true;
}


//! PredatorStateRest
PredatorStateRest* PredatorStateRest::GetInstance()
{
	static PredatorStateRest instance;
	return &instance;
}

void PredatorStateRest::Enter(Predator* p)
{
	std::cout << p->GetEnityName() << " Began Resting\n";
}

void PredatorStateRest::Execute(Predator* p)
{
	srand((unsigned int)time(0));
	int r = rand() % 100 + 1;

	if (r == 1)
	{
		EntityManager& entityManager = EntityManager::GetInstance();
	}


}

void PredatorStateRest::Exit(Predator* p)
{
	std::cout << p->GetEnityName() << ": Finished Resting\n";
}

bool PredatorStateRest::OnMessage(Predator* p, const Message& m)
{
	std::cout << p->GetEnityName() << "<PredatorStateRest::OnMessage>: Message Received\n";

	return true;
}